package com.dt.okhttp;

import com.firmail.mock.util.GsonUtils;
import okhttp3.*;
import org.apache.commons.collections.MapUtils;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.TimeUnit;

public class HttpClientManager {
    private static HttpClientManager httpClientMgr = null;
    private static final String CONTENT_TYPE_LABEL = "Content-Type";
    private static final String CONTENT_TYPE_VALUE_JSON = "application/json; charset=utf-8";
    public static final MediaType MEDIATYPE_JSON = MediaType.parse("application/json; charset=utf-8");
    public static final MediaType MEDIATYPE_FILE = MediaType.parse("text/x-markdown; charset=utf-8");

    @Override
    public int hashCode() {
        return super.hashCode();
    }

    private volatile OkHttpClient okHttpClient;

    public static HttpClientManager getInstance() {
        if (httpClientMgr == null) {
            synchronized (HttpClientManager.class) {
                if (httpClientMgr == null) {
                    httpClientMgr = new HttpClientManager();
                }
            }
        }
        return httpClientMgr;
    }

    private HttpClientManager() {
        okHttpClient = new OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(300, TimeUnit.SECONDS).readTimeout(300, TimeUnit.SECONDS).build();
    }

    public String getSync(String url, Map<String, String> header, Map<String, Object> param) throws Exception {
        Map<String, String> map = new HashMap<>();
        map.put(CONTENT_TYPE_LABEL, CONTENT_TYPE_VALUE_JSON);
        if (MapUtils.isNotEmpty(header)) {
            map.putAll(header);
        }
        Headers headers = Headers.of(map);
        String content = "";
        if (param != null) {
            content = "?";
            Iterator<Entry<String, Object>> it = param.entrySet().iterator();
            while (it.hasNext()) {
                Entry<String, Object> entry = it.next();
                content += entry.getKey() + "=" + entry.getValue();
                if (it.hasNext()) {
                    content += "&";
                }
            }
        }

        String fullUrl = url;
        if (content.length() > 1) {
            fullUrl = url + content;
        }
        Request request = new Request.Builder().url(fullUrl).headers(headers).get().build();
        return this.okHttpClient.newCall(request).execute().body().string();
    }

    private String postSync(String url, Map<String, String> header, Map<String, Object> param) throws Exception {
        Map<String, String> map = new HashMap<>();
        map.put(CONTENT_TYPE_LABEL, CONTENT_TYPE_VALUE_JSON);
        if (MapUtils.isNotEmpty(header)) {
            map.putAll(header);
        }
        Headers headers = Headers.of(map);
        RequestBody rb = RequestBody.create(MEDIATYPE_JSON, GsonUtils.toJson(param));
//		System.out.println("》》》》》》》》》》》》》》》》RequestBody : -》 "+GsonUtils.toJson(param));
        Request request = new Request.Builder().url(url).headers(headers)
                .addHeader(CONTENT_TYPE_LABEL, CONTENT_TYPE_VALUE_JSON).post(rb).build();
        return this.okHttpClient.newCall(request).execute().body().string();
    }

    private String putSync(String url, Map<String, String> header, Map<String, Object> param) throws Exception {
        Map<String, String> map = new HashMap<>();
        map.put(CONTENT_TYPE_LABEL, CONTENT_TYPE_VALUE_JSON);
        if (MapUtils.isNotEmpty(header)) {
            map.putAll(header);
        }
        Headers headers = Headers.of(map);
        RequestBody rb = RequestBody.create(MEDIATYPE_JSON, GsonUtils.toJson(param));
        Request request = new Request.Builder().url(url).headers(headers)
                .addHeader(CONTENT_TYPE_LABEL, CONTENT_TYPE_VALUE_JSON).put(rb).build();
        return this.okHttpClient.newCall(request).execute().body().string();
    }

    private String deleteSync(String url, Map<String, String> header, Map<String, Object> param) throws Exception {
        Map<String, String> map = new HashMap<>();
        map.put(CONTENT_TYPE_LABEL, CONTENT_TYPE_VALUE_JSON);
        if (MapUtils.isNotEmpty(header)) {
            map.putAll(header);
        }
        Headers headers = Headers.of(map);
        RequestBody rb = RequestBody.create(MEDIATYPE_JSON, GsonUtils.toJson(param));
        Request request = new Request.Builder().url(url).headers(headers)
                .addHeader(CONTENT_TYPE_LABEL, CONTENT_TYPE_VALUE_JSON).delete(rb).build();
        return this.okHttpClient.newCall(request).execute().body().string();
    }

    public String postSync(String url, Map<String, String> header, Map<String, Object> param, boolean bodyisjson)
            throws Exception {
        if (bodyisjson) {
            return postSync(url, header, param);
        } else {
            Map<String, String> map = new HashMap<>();
            map.put(CONTENT_TYPE_LABEL, CONTENT_TYPE_VALUE_JSON);
            if (MapUtils.isNotEmpty(header)) {
                map.putAll(header);
            }
            Headers headers = Headers.of(map);
            String content = "?";
            Iterator<Entry<String, Object>> it = param.entrySet().iterator();
            while (it.hasNext()) {
                Entry<String, Object> entry = it.next();
                content += entry.getKey() + "=" + entry.getValue();
                if (it.hasNext()) {
                    content += "&";
                }
            }
            String fullUrl = url;
            if (content.length() > 1) {
                fullUrl = url + content;
            }
            RequestBody rb = RequestBody.create(MEDIATYPE_JSON, "");
            Request request = new Request.Builder().url(fullUrl).headers(headers).post(rb).build();
            return this.okHttpClient.newCall(request).execute().body().string();
        }

    }

    public String putSync(String url, Map<String, String> header, Map<String, Object> param, boolean bodyisjson)
            throws Exception {
        if (bodyisjson) {
            return putSync(url, header, param);
        } else {
            Map<String, String> map = new HashMap<>();
            map.put(CONTENT_TYPE_LABEL, CONTENT_TYPE_VALUE_JSON);
            if (MapUtils.isNotEmpty(header)) {
                map.putAll(header);
            }
            Headers headers = Headers.of(map);
            String content = "?";
            Iterator<Entry<String, Object>> it = param.entrySet().iterator();
            while (it.hasNext()) {
                Entry<String, Object> entry = it.next();
                content += entry.getKey() + "=" + entry.getValue();
                if (it.hasNext()) {
                    content += "&";
                }
            }
            String fullUrl = url;
            if (content.length() > 1) {
                fullUrl = url + content;
            }
            RequestBody rb = RequestBody.create(MEDIATYPE_JSON, "");

            Request request = new Request.Builder().url(fullUrl).headers(headers).put(rb).build();
            return this.okHttpClient.newCall(request).execute().body().string();
        }

    }

    public String deleteSync(String url, Map<String, String> header, Map<String, Object> param, boolean bodyisjson)
            throws Exception {
        if (bodyisjson) {
            return deleteSync(url, header, param);
        } else {
            Map<String, String> map = new HashMap<>();
            map.put(CONTENT_TYPE_LABEL, CONTENT_TYPE_VALUE_JSON);
            if (MapUtils.isNotEmpty(header)) {
                map.putAll(header);
            }
            Headers headers = Headers.of(map);
            String content = "?";
            Iterator<Entry<String, Object>> it = param.entrySet().iterator();
            while (it.hasNext()) {
                Entry<String, Object> entry = it.next();
                content += entry.getKey() + "=" + entry.getValue();
                if (it.hasNext()) {
                    content += "&";
                }
            }
            String fullUrl = url;
            if (content.length() > 1) {
                fullUrl = url + content;
            }
            RequestBody rb = RequestBody.create(MEDIATYPE_JSON, "");

            Request request = new Request.Builder().url(fullUrl).headers(headers).delete(rb).build();
            return this.okHttpClient.newCall(request).execute().body().string();
        }

    }

    public String upload(String url, Map<String, String> header, Map<String, Object> parameter, File filePath, String key)
            throws Exception {
        String BOUNDARY = java.util.UUID.randomUUID().toString();
        String PREFIX = "--", LINEND = "\r\n";
        String MULTIPART_FROM_DATA = "multipart/form-data";
        String CHARSET = "UTF-8";

        URL uri = new URL(url);
        HttpURLConnection conn = (HttpURLConnection) uri.openConnection();
        conn.setReadTimeout(5 * 1000); // 缓存的最长时间
        conn.setDoInput(true);// 允许输入
        conn.setDoOutput(true);// 允许输出
        conn.setUseCaches(false); // 不允许使用缓存
        conn.setRequestMethod("POST");
        conn.setRequestProperty("connection", "keep-alive");
        conn.setRequestProperty("Charsert", "UTF-8");
        conn.setRequestProperty("Content-Type", MULTIPART_FROM_DATA + ";boundary=" + BOUNDARY);
        Set<Entry<String, String>> set = header.entrySet();
        for (Entry<String, String> entry : set) {
            conn.setRequestProperty(entry.getKey(), entry.getValue());
        }
        // 首先组拼文本类型的参数
        StringBuilder sb = new StringBuilder();
        for (Entry<String, Object> entry : parameter.entrySet()) {
            sb.append(PREFIX);
            sb.append(BOUNDARY);
            sb.append(LINEND);
            sb.append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + LINEND);
            sb.append("Content-Type: text/plain; charset=" + CHARSET + LINEND);
            sb.append("Content-Transfer-Encoding: 8bit" + LINEND);
            sb.append(LINEND);
            sb.append(entry.getValue());
            sb.append(LINEND);
        }
        DataOutputStream outStream = new DataOutputStream(conn.getOutputStream());
        outStream.write(sb.toString().getBytes());
        // 发送文件数据
        StringBuilder sb1 = new StringBuilder();
        sb1.append(PREFIX);
        sb1.append(BOUNDARY);
        sb1.append(LINEND);
        // name是post中传参的键 filename是文件的名称
        String fileName = filePath.getName();
        sb1.append("Content-Disposition: form-data; name=\"" + key + "\"; filename=\"" + fileName + "\"" + LINEND);
        sb1.append("Content-Type: application/octet-stream; charset=" + CHARSET + LINEND);
        sb1.append(LINEND);
        outStream.write(sb1.toString().getBytes());
        InputStream is = new FileInputStream(filePath);
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = is.read(buffer)) != -1) {
            outStream.write(buffer, 0, len);
        }
        is.close();
        outStream.write(LINEND.getBytes());
        // 请求结束标志
        byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINEND).getBytes();
        outStream.write(end_data);
        outStream.flush();
        // 得到响应码
        int res = conn.getResponseCode();

        if (res == 200) {

        }
        outStream.close();
        InputStream istrem = conn.getInputStream();
        byte[] b = new byte[2048];
        StringBuffer buff = new StringBuffer();
        while (istrem.read(b) != -1) {
            buff.append(new String(b, 0, b.length));
        }
        conn.disconnect();
        return buff.toString();
    }

}
